/**
 *	处理客户端接收的请求
 *	开发者：雨中磐石
 *	地址：www.rockoa.com
 *	日期：2023-07-19
 */


package com.framerock.server;

import com.framerock.baselib.AA;
import com.framerock.baselib.CDate;


import com.framerock.baselib.CLog;
import com.framerock.baselib.Rock;
import com.framerock.cache.Cache;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;

import java.net.Socket;
import java.nio.ByteBuffer;
import java.nio.charset.StandardCharsets;
import java.util.Map;

/**
 * 处理客户端接收的请求
 * */
public class HttpClient {

    private String printString = "",requestString = "";
    private Socket clineSocket;
    private Map<String, String> sHeader;

    /**
     * 进程名称
     * */
    public Thread nowThread     = null;

    /**
     * 当前的数量
     * */
    public int nowCount         = 0;

    /**
     * 处理客户端接收的请求
     * @param socket 链接信息
     * */
    public HttpClient(Socket socket) {
        clineSocket = socket;
        sHeader		= Rock.getMap();
        if(clineSocket != null)initRequest();
    }


    /**
     * 初始信息
     * */
    private void initRequest()
    {
        String request  = "",postdata = "",Method= "";
        request         = getInputString();
        requestString   = request;
        //CLog.debug("request("+clineSocket.getInetAddress()+":"+clineSocket.getPort()+"):\n"+request);
        String ip   = clineSocket.getInetAddress().toString();
        if(ip.substring(0,1).equals("/"))ip = ip.substring(1);
        sHeader.put("ip", ip);
        if(Rock.isEmpt(request))return;

        String arr[] = request.split("\r\n"),arr1[],str1,val;
        for(int i=1; i<arr.length; i++){
            str1 = arr[i];
            if(Rock.isEmpt(str1))break;
            arr1 = str1.split(": ");
            val  = "";
            if(arr1.length==1)arr1 = str1.split(":");
            if(arr1.length > 1)val  = arr1[1];
            sHeader.put(arr1[0], val);
        }
        arr1        = arr[0].split(" ");
        Method      = arr1[0].toUpperCase();
        sHeader.put("Method", Method);
        sHeader.put("Path", arr1[1]);
        if(Method.equals("POST") || Method.equals("SOCKETPOST")){
            arr1 = request.split("\r\n\r\n");
            if(arr1.length>1)postdata = arr1[1];
        }
        sHeader.put("postdata", postdata);
    }


    private InputStream socketIn = null;

    /**
     * 读取发送过来的数据
     * */
    public String getInputString()
    {
        String request = "",bstr = "";
        try {
            if(socketIn==null)socketIn = clineSocket.getInputStream();
            int size	= 0;
            int rsize	= 1024 * 1024 * 1;  //缓存区1M

            byte[] buffer = new byte[rsize];
            int bytesRead = 0;
            while(bytesRead > -1) {
                bytesRead = socketIn.read(buffer);
                if(bytesRead==-1)break;
                bstr = new String(buffer, 0, bytesRead);
                request+=bstr;
                size = socketIn.available();
                if(size==0)break;
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        return request;
    }

    /**
     * 是否为空关闭是否为空
     * */
    public Boolean isClose()
    {
        return (clineSocket == null) ? true : false;
    }

    /**
     * 获取流的数据
     * */
    public ByteBuffer getByteBuffer()
    {
        try {
            if(socketIn==null)socketIn = clineSocket.getInputStream();
            int size	= 0;
            int rsize	= 1024 * 1024 * 1;  //缓存区1M
            ByteBuffer byteBuffer = ByteBuffer.allocate(1024*1024);
            byteBuffer.clear();
            byte[] buffer = new byte[rsize];
            int bytesRead = 0;
            while(bytesRead > -1) {
                bytesRead = socketIn.read(buffer); //一直等待
                if(bytesRead==-1)break;
                byteBuffer.put(buffer, 0, bytesRead);
                size = socketIn.available();
                if(size==0)break;
            }
            byteBuffer.flip(); // 重要：准备ByteBuffer进行读取
            return byteBuffer;
        } catch (IOException e) {
            //e.printStackTrace();
            CLog.error(e.toString());
            close();
        }
        return null;
    }

    /**
     * 设置返回http头
     * */
    public void setHttpStatus(int code)
    {
        printString = "HTTP/1.1 "+code+" OK\n";
    }

    /**
     * 设置header
     * */
    public void setHeader(String key, String type)
    {
        printString+=""+key+": "+type+"\n";
    }

    /**
     * 设置输出内容
     * */
    public void setHttpBody(String str)
    {
        if(!Rock.isEmpt(str))setContentLength(str.getBytes(StandardCharsets.UTF_8).length);
        printString+="\n"+str+"";
    }

    /**
     * 设置长度
     * */
    public void setContentLength(long len)
    {
        setHeader("Content-Length", ""+len);
    }

    /**
     * 输入内容
     * */
    private OutputStream socketOut = null;
    public void writeResponse()
    {
        writeResponse(printString);
    }

    /**
     * 输入内容
     * @param str 内容
     * */
    public void writeResponse(String str)
    {
        writeResponse(str.getBytes());
    }

    /**
     * 输入内容
     * @param buffer 字节内容
     * */
    public void writeResponse(byte[] buffer)
    {
        try {
            getOutputStream();
            socketOut.write(buffer);
            socketOut.flush();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * 读取流
     * */
    public OutputStream getOutputStream()
    {
        try {
            if(socketOut == null) socketOut  = clineSocket.getOutputStream();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return socketOut;
    }

    /**
     * 写入消息
     * @param buffer 写入内容
     * */
    public Boolean writeResponse(ByteBuffer buffer)
    {
        if(clineSocket == null )return false;
        try {
            getOutputStream();
            socketOut.write(buffer.array(), 0, buffer.limit());
            socketOut.flush();
            return true;
        } catch (IOException e) {
            e.printStackTrace();
            return false;
        }
    }

    /**
     * 设置基础的header
     * */
    public void setBaseHeader(String type)
    {
        setHeader("Content-Type",type);
        setHeader("Date", CDate.now());
        setHeader("Server", ""+ AA.APPTYPE+"/"+AA.VERSION+",httpserver");
        setHeader("Copyright", "www.rockoa.com");
    }

    /**
     * http的显示输出
     * */
    public void showHttp(int code, String body)
    {
        setHttpStatus(code);
        setBaseHeader("text/html;charset=utf-8");
        setHeader("Access-Control-Allow-Headers", "X-Requested-With");
        setHeader("Access-Control-Allow-Origin", "*");
        setHeader("Access-Control-Allow-Credentials", "true");
        setHttpBody(body);
        writeResponse();
    }

    /**
     * 获取头部header
     * */
    public String getHeader(String key)
    {
        String str = sHeader.get(key);
        if(str==null)str = "";
        return str;
    }

    /**
     * 请求的路径
     * */
    public String getPath()
    {
        String path = getHeader("Path");
        if(!Rock.isEmpt(path)) {
            String arr[] = path.split("\\?");
            path = arr[0];
        }
        return path;
    }

    /**
     * 获取请求类型
     * */
    public String getMethod()
    {
        String str = getHeader("Method");
        if(Rock.isEmpt(str))str = "GET";
        return str;
    }

    /**
     * 获取请求类型
     * */
    public String getAccept()
    {
        String str = getHeader("Accept");
        if(!Rock.isEmpt(str)) {
            String arr[] = str.split(",");
            str = arr[0];
        }
        return str;
    }

    /**
     * 获取浏览器信息
     * */
    public String getUserAgent()
    {
        String str = getHeader("User-Agent");
        return str;
    }

    /**
     * 获取Origin来验证来源
     * */
    public String getOrigin()
    {
        String str = getHeader("Origin");
        return str;
    }

    /**
     * 获取控制器路由路径
     * */
    public String getRouter()
    {
        String path   = getPath();
        String router = HttpRouter.getRouter(path);
        if(Rock.isEmpt(router))router = path;
        if(Rock.isEmpt(router))return "";
        return router;
    }

    /**
     * 关闭
     * */
    public void close()
    {
        try {
            if(clineSocket != null)clineSocket.close();
            clineSocket = null;
            socketOut = null;
            socketIn  = null;
        } catch (IOException e) {
            e.printStackTrace();
        }
        if(nowThread != null)nowThread.interrupt();
    }
}